package fr.asip.cps3.exemple.modele.objets;

import iaik.pkcs.pkcs11.wrapper.CK_ATTRIBUTE;
import iaik.pkcs.pkcs11.wrapper.PKCS11;
import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;
import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;

import org.apache.log4j.Logger;

import fr.asip.cps3.exemple.modele.exceptions.ExceptionObjet;
import fr.asip.cps3.exemple.modele.exceptions.ExceptionProgrammeExemple;
import fr.asip.cps3.exemple.modele.traitements.util.TraitementsUtil;

/**
 * Classe modélisant une clé
 */
public class Cle {

	/**
	 * Le loggeur
	 */
	 private static Logger log = Logger.getLogger(Cle.class);
	 
	/**
	 * Identifiant de la clé
	 */
	private long idCle;

	/**
	 * Taille de la cle
	 */
	private long tailleCle = -1;

	/**
	 * Genre de la clef (Secrète/Privée/Publique)
	 */
	private long genreCle = -1;
	
	/**
	 * Type de la cle
	 */
	private long typeCle = -1;
	
	/**
	 * Constructeur
	 * @param librairie Librairie PKCS#11 à utiliser
	 * @param idSession Identifiant de la session
	 * @param idCle Identifiant de la clé
	 * @param genreCle Genre de clé (Secrète/Privée/Publique)
	 * @throws ExceptionObjet 
	 */	
	public Cle(PKCS11 librairie, long idSession, long idCle, long genreCle) throws ExceptionObjet {
		
		this.idCle = idCle;
		this.genreCle = genreCle;
		
		chargeInfo(librairie, idSession);
		
	}
	
	/**
	 * (Re)chargement explicite des informations de la clé
	 * @param librairie Librairie PKCS#11 à utiliser
	 * @param idSession Identifiant de la session
	 * @throws ExceptionObjet 
	 */
	public void chargeInfo(PKCS11 librairie, long idSession) throws ExceptionObjet{
		
		if(librairie != null) {
			
			try {
				
				// Collecte de quelques informations concernant la clé
				
				//type et taille
				CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[2];
				attributes[0] = new CK_ATTRIBUTE();
				attributes[0].type = PKCS11Constants.CKA_KEY_TYPE;
				attributes[1] = new CK_ATTRIBUTE();
				attributes[1].type = PKCS11Constants.CKA_MODULUS_BITS;
				librairie.C_GetAttributeValue(idSession, this.idCle, attributes);
				if(attributes != null && attributes.length != 0) {
					try {
						typeCle = (Long)attributes[0].pValue;
						tailleCle = (Long)attributes[1].pValue;
					} catch(ClassCastException e) {
						System.out.println("ERREUR\n:"+e.getMessage());
					}	
				}
				
			} catch (PKCS11Exception e) {
				
				// Si une erreur PKCS#11 est rencontrée on log et on lève l'exception
				log.error("Une erreur est survenue lors de la recuperation des informations de la cle : "+TraitementsUtil.retranscritCodeRetour(e.getErrorCode()));
				throw new ExceptionObjet(ExceptionProgrammeExemple.TYPE_OBJET_CLE, "Une erreur est survenue lors de la récuperation des informations de la clé");
				
			}

		} else {
			
			// Si la librairie est nulle il est impossible de récupérer les informations de la clé
			log.error("La librairie est nulle");
			throw new ExceptionObjet(ExceptionProgrammeExemple.TYPE_OBJET_CLE, "La librairie est nulle");
			
		}

	}
	
	/**
	 * Accesseur
	 * @return Libellé de la clé
	 */
	public String getLibelle() {
		
		return "Clé "+Long.toString(idCle)+"/"+tailleCle+"/"+TraitementsUtil.getNomTypeCle(typeCle).replaceAll("_", " ").replaceAll("CKK", "");
		
	}

	/**
	 * Accesseur
	 * @return Identifiant de l'objet clé
	 */
	public long getIdCle() {
		
		return idCle;
		
	}

	/**
	 * Accesseur
	 * @return Taille de la clé
	 */
	public long getTailleCle() {
		
		return tailleCle;
		
	}

	/**
	 * La clé est-elle privée?
	 * @return Réponse
	 */
	public boolean isClePrivee() {
		
		return genreCle == PKCS11Constants.CKO_PRIVATE_KEY;
		
	}

	/**
	 * La clé est-elle publique?
	 * @return Réponse
	 */
	public boolean isClePublique() {
		
		return genreCle == PKCS11Constants.CKO_PUBLIC_KEY;
		
	}
	
	/**
	 * La clé est-elle secrète
	 * @return Réponse
	 */
	public boolean isCleSecrete() {
		
		return genreCle == PKCS11Constants.CKO_SECRET_KEY;
		
	}

	
}
